package com.company.common.util;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.company.common.enums.ExecuteErrorEnum;
import com.company.common.enums.TableNamePrefixEnum;
import com.company.common.exception.BizException;
import com.company.user.entity.ConsulCloudEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * Description: company
 * Created by hekai on 2021/3/24 11:21
 * 雪花id生成器
 */
@Component
public class IdentifierGeneratorUtil {

    private static IdentifierGenerator identifierGenerator = new DefaultIdentifierGenerator();

    public static IdentifierGenerator getIdentifierGenerator(){
        return identifierGenerator;
    }

    //计数
    private static Integer num = 0;

    public static String dateStr;

    @Resource
    private ConsulCloudEntity consulCloudEntity;

    //本类静态属性
    private static IdentifierGeneratorUtil identifierGeneratorUtil;

    // 初始化的时候，将本类中的consulCloudEntity赋值给静态的本类变量
    @PostConstruct
    public void init() {
        identifierGeneratorUtil = this;
        identifierGeneratorUtil.consulCloudEntity = this.consulCloudEntity;
    }

    /**
     * 19位随机数字
     * @param t
     * @param <T>
     * @return
     */
    public static <T> String getNumberId(T t){
        return ""+identifierGenerator.nextId(t);
    }

    /**
     * 32位随机雪花字符
     * @param t
     * @param <T>
     * @return
     */
    public static <T> String getUUID(T t){
        return identifierGenerator.nextUUID(t);
    }

    /**
     * 生成ID
     * 规则:
     * 类枚举（大写两位字母） + 当前服务器注册在服务发现的ID前两位 + 标准时间yyyyMMddHHmmss + ID计数器的format %06d
     * @param tableNamePrefixEnum 表名枚举
     * @return
     */
    public static String getOwnId(TableNamePrefixEnum tableNamePrefixEnum){

        //ID拼接
        StringBuilder ownId = new StringBuilder();

        //获取表名枚举
        String tablePrefix = tableNamePrefixEnum.getTablePrefix();
        ownId.append(tablePrefix);

        //当前服务器的instanceId的前两位
        String instanceId = identifierGeneratorUtil.identifierGeneratorUtil.consulCloudEntity.getInstanceId();
        //小于两个字符抛异常
        if(StringUtils.isBlank(instanceId) || instanceId.length() < 2){
            //服务器ID不符合规则,至少是两位字符！
            throw new BizException(ExecuteErrorEnum.IDEXECUTE_SERVICEINSTACEIDNOMATCHERROR_ENUM);
        }
        //取服务器ID前两位
        ownId.append(instanceId, 0, 2);

        if(StringUtils.isBlank(dateStr)){
            dateStr = DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN);
        }

        //当前服务器的标准时间yyyyMMddHHmmss
        ownId.append(dateStr);

        //程序计数
        ownId.append(getNum());

        return ownId.toString();
    }

    /**
     * ID计数器 从1开始，程序重新运行开始计数 ,加锁
     * @return 00000[i] [i]代表自增数字
     */
    public static synchronized String getNum(){
        num++;
        if(num > 999999){
            num = 1;
            //设置重新获取时间
            dateStr = null;
        }
        return String.format("%06d",num);
    }

}
